//
//  UIApplication+Info.m
//  iCJTools
//
//  Created by YCJ on 2020/7/24.
//  Copyright © 2020 YCJ. All rights reserved.
//

#import "UIApplication+Info.h"
#import "FastKeyTool.h"
#import "CommonTool.h"

#import <ifaddrs.h>
#import <arpa/inet.h>
#import <net/if.h>

#define IOS_CELLULAR    @"pdp_ip0"
#define IOS_WIFI        @"en0"
#define IOS_VPN         @"utun0"
#define IP_ADDR_IPv4    @"ipv4"
#define IP_ADDR_IPv6    @"ipv6"

NSString *appName;
NSString *appBundleId;
NSString *appVersion;
NSString *deviceToken;
NSString *deviceModelName;
NSString *deviceOSVersion;

NSString *ip;
NSString *port;
NSString *mac;
NSString *imei;

@implementation UIApplication (Info)

+ (NSString *)appName
{
    if (!appName) {
        NSDictionary *dicInfo = [[NSBundle mainBundle] infoDictionary];
        appName = [dicInfo objectForKey:@"CFBundleDisplayName"];
    }
    return appName;
}

+ (NSString *)appBundleId
{
    if (!appBundleId) {
        NSDictionary *dicInfo = [[NSBundle mainBundle] infoDictionary];
        appBundleId = [dicInfo objectForKey:@"CFBundleIdentifier"];
    }
    return appBundleId;
}

+ (NSString *)appVersion
{
    if (!appVersion) {
        NSDictionary *dicInfo = [[NSBundle mainBundle] infoDictionary];
        appVersion = [dicInfo objectForKey:@"CFBundleShortVersionString"];
    }
    return appVersion;
}

+ (UIApplicationStatus)appStatus
{
    if([UIApplication sharedApplication].applicationState == UIApplicationStateBackground ||
       [UIApplication sharedApplication].applicationState == UIApplicationStateInactive){
        return UIApplicationStatusBackground;
    }else{
        return UIApplicationStatusForeground;
    }
}

+ (NSString *)appStatusString
{
    if (UIApplication.appStatus == UIApplicationStatusForeground) {
        return @"前台";
    } else {
        return @"后台";
    }
}

+ (NSString *)deviceToken
{
    if (!deviceToken) {
        
        deviceToken = (NSString *)[FastKeyTool dataForService:UIApplication.appBundleId];
        
        //首次执行该方法时，uuid为空
        if ([deviceToken isEqualToString:@""] || !deviceToken) {
            
            //生成一个uuid的方法
            deviceToken = [[UIDevice currentDevice] identifierForVendor].UUIDString;
            
            //将该uuid保存到keychain
            [FastKeyTool saveData:deviceToken forService:UIApplication.appBundleId];
        }
    }
    return deviceToken;
}

+ (void)deleteDeviceToken
{
    [FastKeyTool deleteDataForService:UIApplication.appBundleId];
}

+ (NSString *)deviceModelName
{
    if (!deviceModelName) {
        deviceModelName = [[UIDevice currentDevice] deviceType];
    }
    return deviceModelName;
}

+ (NSString *)deviceOSVersion
{
    if (!deviceModelName) {
        NSString *version = [[UIDevice currentDevice] systemVersion];
        deviceModelName = [NSString stringWithFormat:@"iOS %@",version];
    }
    return deviceModelName;
}

+ (NSString *)ip
{
    ip = [self getIPAddress:YES];
    return ip;
}

+ (NSString *)port
{
    return @"";
}

+ (NSString *)mac
{
    return @"";
}

+ (NSString *)imei
{
    return @"";
}

#pragma mark - 获取设备当前网络IP地址
+ (NSString *)getIPAddress:(BOOL)preferIPv4
{
    NSArray *searchArray = preferIPv4 ?
    @[ IOS_VPN @"/" IP_ADDR_IPv4, IOS_VPN @"/" IP_ADDR_IPv6, IOS_WIFI @"/" IP_ADDR_IPv4, IOS_WIFI @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6 ] :
    @[ IOS_VPN @"/" IP_ADDR_IPv6, IOS_VPN @"/" IP_ADDR_IPv4, IOS_WIFI @"/" IP_ADDR_IPv6, IOS_WIFI @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4 ] ;
    
    NSDictionary *addresses = [self getIPAddresses];
    NSLog(@"addresses: %@", addresses);
    
    __block NSString *address;
    [searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop)
     {
         address = addresses[key];
         //筛选出IP地址格式
         if([self isValidatIP:address]) *stop = YES;
     } ];
    return address ? address : @"0.0.0.0";
}

+ (BOOL)isValidatIP:(NSString *)ipAddress {
    if (ipAddress.length == 0) {
        return NO;
    }
    NSString *urlRegEx = @"^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
    "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
    "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
    "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
    
    NSError *error;
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:urlRegEx options:0 error:&error];
    
    if (regex != nil) {
        NSTextCheckingResult *firstMatch=[regex firstMatchInString:ipAddress options:0 range:NSMakeRange(0, [ipAddress length])];
        
        if (firstMatch) {
            NSRange resultRange = [firstMatch rangeAtIndex:0];
            NSString *result=[ipAddress substringWithRange:resultRange];
            //输出结果
            NSLog(@"%@",result);
            return YES;
        }
    }
    return NO;
}


+ (NSDictionary *)getIPAddresses
{
    NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8];
    
    // retrieve the current interfaces - returns 0 on success
    struct ifaddrs *interfaces;
    if(!getifaddrs(&interfaces)) {
        // Loop through linked list of interfaces
        struct ifaddrs *interface;
        for(interface=interfaces; interface; interface=interface->ifa_next) {
            if(!(interface->ifa_flags & IFF_UP) /* || (interface->ifa_flags & IFF_LOOPBACK) */ ) {
                continue; // deeply nested code harder to read
            }
            const struct sockaddr_in *addr = (const struct sockaddr_in*)interface->ifa_addr;
            char addrBuf[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) ];
            if(addr && (addr->sin_family==AF_INET || addr->sin_family==AF_INET6)) {
                NSString *name = [NSString stringWithUTF8String:interface->ifa_name];
                NSString *type;
                if(addr->sin_family == AF_INET) {
                    if(inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN)) {
                        type = IP_ADDR_IPv4;
                    }
                } else {
                    const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)interface->ifa_addr;
                    if(inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN)) {
                        type = IP_ADDR_IPv6;
                    }
                }
                if(type) {
                    NSString *key = [NSString stringWithFormat:@"%@/%@", name, type];
                    addresses[key] = [NSString stringWithUTF8String:addrBuf];
                }
            }
        }
        // Free memory
        freeifaddrs(interfaces);
    }
    return [addresses count] ? addresses : nil;
}

//是否网络代理打开
+ (BOOL)isProxyOpen
{
    NSDictionary *proxySettings =  (__bridge NSDictionary *)(CFNetworkCopySystemProxySettings());
    NSArray *proxies = (__bridge NSArray *)(CFNetworkCopyProxiesForURL((__bridge CFURLRef _Nonnull)([NSURL URLWithString:@"http://www.baidu.com"]), (__bridge CFDictionaryRef _Nonnull)(proxySettings)));
    NSDictionary *settings = [proxies objectAtIndex:0];
    
    NSLog(@"host=%@", [settings objectForKey:(NSString *)kCFProxyHostNameKey]);
    NSLog(@"port=%@", [settings objectForKey:(NSString *)kCFProxyPortNumberKey]);
    NSLog(@"type=%@", [settings objectForKey:(NSString *)kCFProxyTypeKey]);
    
    if ([[settings objectForKey:(NSString *)kCFProxyTypeKey] isEqualToString:@"kCFProxyTypeNone"]){
        //没有设置代理
        return NO;
    }else{
        //设置代理了
        return YES;
    }
}

//是否越狱
+ (BOOL)isJailBroken
{
    BOOL isJailBroken = ([self isJailBreakViaFi] && [self isJailBreakViaOp] && [self isJailBreakViaAu] && [self isJailBreakViaEv]);
    return isJailBroken;
}

#define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0])

const char* jailbreak_tool_pathes[] = {
    "/Applications/Cydia.app",
    "/Library/MobileSubstrate/MobileSubstrate.dylib",
    "/bin/bash",
    "/usr/sbin/sshd",
    "/etc/apt"
};

//通过特殊文件
+ (BOOL)isJailBreakViaFi
{
    for (int i=0; i<ARRAY_SIZE(jailbreak_tool_pathes); i++) {
        if ([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithUTF8String:jailbreak_tool_pathes[i]]]) {
            NSLog(@"The device is jail broken!");
            return YES;
        }
    }
    NSLog(@"The device is NOT jail broken!");
    return NO;
}

//通过打开应用
+ (BOOL)isJailBreakViaOp
{
    if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"cydia://"]]) {
        NSLog(@"The device is jail broken!");
        return YES;
    }
    NSLog(@"The device is NOT jail broken!");
    return NO;
}

#define USER_APP_PATH  @"/User/Applications/"
//通过获取应用信息
+ (BOOL)isJailBreakViaAu
{
    if ([[NSFileManager defaultManager] fileExistsAtPath:USER_APP_PATH]) {
        NSLog(@"The device is jail broken!");
        NSArray *applist = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:USER_APP_PATH error:nil];
        NSLog(@"applist = %@", applist);
        return YES;
    }
    NSLog(@"The device is NOT jail broken!");
    return NO;
}

char* printEnv(void)
{
    char *env = getenv("DYLD_INSERT_LIBRARIES");
    NSLog(@"%s", env);
    return env;
}

//通过环境变量
+ (BOOL)isJailBreakViaEv
{
    if (printEnv()) {
        NSLog(@"The device is jail broken!");
        return YES;
    }
    NSLog(@"The device is NOT jail broken!");
    return NO;
}

@end

